﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace sand_game_core
{
    public struct newParticle
    {
        private byte R;
        private byte G;
        private byte B;
        private byte A;
        public byte myType;
        internal byte L;
        internal static Color litColor;
        public static void setParticle(ref newParticle p, byte MyType, byte Red, byte Green, byte Blue, byte Alpha)
        {
            p.R = Red;
            p.G = Green;
            p.B = Blue;
            p.A = Alpha;
            p.myType = MyType;
            p.L = 0;
        }
        public static void setParticle(ref newParticle p, byte MyType)
        {
            setParticle(ref p, MyType, p.L);
        }
        public static void setParticle(ref newParticle p, byte MyType, byte light)
        {
            switch (MyType)
            {
                case 0: //done
                    p.R = 0;
                    p.G = 0;
                    p.B = 0;
                    p.A = 0;
                    break;
                case 1: //done
                    p.R = (byte)(176 + random.rnd.Next(60));
                    p.G = (byte)(170 + random.rnd.Next(60));
                    p.B = (byte)(70 + random.rnd.Next(60));
                    p.A = 255;
                    break;
                case 2: //done
                    p.R = (byte)(169 + random.rnd.Next(38));
                    p.G = (byte)(169 + random.rnd.Next(38));
                    p.B = (byte)(166 + random.rnd.Next(32));
                    p.A = 255;
                    break;
                case 3: //done
                    p.R = (byte)(0 + random.rnd.Next(60));
                    p.G = (byte)(50 + random.rnd.Next(60));
                    p.B = (byte)(100 + random.rnd.Next(60));
                    p.A = 130;
                    break;
                case 4:
                    p.R = (byte)(180 + random.rnd.Next(75));
                    p.G = (byte)(100 + random.rnd.Next(60));
                    p.B = (byte)(50 + random.rnd.Next(60));
                    p.A = 130;
                    break;
                case 5:
                    p.R = (byte)(230 + random.rnd.Next(25));
                    p.G = (byte)(130 + random.rnd.Next(60));
                    p.B = (byte)(60 + random.rnd.Next(60));
                    p.A = 90;
                    break;
                case 6:
                    p.R = (byte)(30 + random.rnd.Next(30));
                    p.G = (byte)(30 + random.rnd.Next(30));
                    p.B = (byte)(30 + random.rnd.Next(30));
                    p.A = 255;
                    break;
                case 7:
                    p.R = (byte)(70 + random.rnd.Next(30));
                    p.G = (byte)(70 + random.rnd.Next(30));
                    p.B = (byte)(70 + random.rnd.Next(30));
                    p.A = 255;
                    break;
            }
            p.myType = MyType;
            p.L = light;
        }
        public static Color getColor(newParticle p)
        {
            litColor.PackedValue = (uint)(
                (p.A << 24) +
                ((p.B - (255 - p.L) > 0 ? (p.B - (255 - p.L)) : 0) << 16) +
                ((p.G - (255 - p.L) > 0 ? (p.G - (255 - p.L)) : 0) << 8) +
                 (p.R - (255 - p.L) > 0 ? (p.R - (255 - p.L)) : 0));
            return litColor;
        }
    }
    public static class NewParticle
    {
        #region fields
        public static Texture2D myImage;
        private static newParticle upParticle;
        private static newParticle downParticle;
        private static byte ammount;
        private static newParticle RightParticle;
        private static newParticle LeftParticle;
        private static newParticle ThisParticle;
        public static newParticle blank;
        public delegate void Update(ref newParticle p, uint x, uint y);
        public static Update toUpdate;
        public delegate void BaseLight(uint x, uint y);
        public static BaseLight Light;
        #endregion
        public static void init()
        {
            blank = new newParticle();
            newParticle.setParticle(ref blank, 0, 0, 0, 0, 0);
            toUpdate = new Update(update);
            Light = new BaseLight(lightMe);
            newParticle.litColor = new Color();
        }
        public static void update(ref newParticle p, uint x, uint y)
        {
            switch (p.myType)
            {
                #region 0: empty
                case 0: //empty
                    break;
                #endregion
                #region 1: sand
                case 1: //sand
                    ammount = (byte)random.rnd.Next(2);
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    RightParticle = x >= 1 ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                    LeftParticle = world.arraywidth > y + 1 ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;

                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }
                    else if (downParticle.myType == 1 && random.rnd.Next(50) == 1)
                    {
                        world.swap(x, y, (uint)(x + (random.rnd.Next(0, 100) < 50 && !(LeftParticle.myType == 1) ? -1 : !(LeftParticle.myType == 1) ? 1 : 0)), y);
                    }
                    else if (LeftParticle.myType == 6)
                    {
                        newParticle.setParticle(ref LeftParticle, 7);
                        newParticle.setParticle(ref p, 7);
                    }
                    else if (RightParticle.myType == 6)
                    {
                        newParticle.setParticle(ref RightParticle, 7);
                        newParticle.setParticle(ref p, 7);
                    }

                    else if (upParticle.myType == 6)
                    {
                        newParticle.setParticle(ref upParticle, 7);
                        newParticle.setParticle(ref p, 7);
                    }
                    else if (downParticle.myType == 6)
                    {
                        newParticle.setParticle(ref downParticle, 7);
                        newParticle.setParticle(ref p, 7);
                    }
                    break;
                #endregion
                #region 2: stone
                case 2:
                    /*downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }*/
                    break;
                #endregion
                #region 3: water
                case 3:
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : NewParticle.blank;
                    ammount = (byte)random.rnd.Next(6);
                    if (downParticle.myType == 0)
                    {
                        world.swap(x, y, x, y - 1);
                    }
                    if (ammount > 3)
                    {
                        RightParticle = x >= ammount ? world.worldParticleLayer[(x - ammount - 3) * world.arraywidth + y] : blank;
                        LeftParticle = world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount - 3) * world.arraywidth + y] : blank;
                        world.swap(x, y, (uint)(x + (random.rnd.Next(2) == 0 ? ammount - 3 : 0)), y);
                        if (LeftParticle.myType == 4)
                        {
                            newParticle.setParticle(ref LeftParticle, 6);
                            newParticle.setParticle(ref p, 6);
                        }
                        else if (RightParticle.myType == 4)
                        {
                            newParticle.setParticle(ref RightParticle, 6);
                            newParticle.setParticle(ref p, 6);
                        }
                        else if (downParticle.myType == 4)
                        {
                            newParticle.setParticle(ref downParticle, 6);
                            newParticle.setParticle(ref p, 6);
                        }
                    }
                    break;
                #endregion
                #region 4: lava
                case 4:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;

                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;

                    ammount = (byte)random.rnd.Next(2);
                    if (ammount > 0)
                    {
                        if (downParticle.myType == 0 || downParticle.myType == 7)
                        {
                            world.swap(x, y, x, y - 1);
                        }
                        RightParticle = x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                        LeftParticle = world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;
                        world.swap(x, y, (uint)(x + (random.rnd.Next(2) == 0 || (RightParticle.myType < 2 && LeftParticle.myType >= 2) ? ammount : -ammount)), y);
                    }

                    else if (downParticle.myType == 1)
                    {
                        newParticle.setParticle(ref downParticle, 4);
                    }
                    else if (LeftParticle.myType == 3)
                    {
                        newParticle.setParticle(ref LeftParticle, 6);
                        newParticle.setParticle(ref p, 6);
                    }
                    else if (RightParticle.myType == 3)
                    {
                        newParticle.setParticle(ref RightParticle, 6);
                        newParticle.setParticle(ref p, 6);
                    }
                    else if (downParticle.myType == 3)
                    {
                        newParticle.setParticle(ref downParticle, 6);
                        newParticle.setParticle(ref p, 6);
                    }
                    else if (LeftParticle.myType == 1)
                    {
                        newParticle.setParticle(ref LeftParticle, 4);
                    }
                    else if (RightParticle.myType == 1)
                    {
                        newParticle.setParticle(ref RightParticle, 4);
                    }
                    else if (upParticle.myType == 1)
                    {
                        newParticle.setParticle(ref upParticle, 4);
                    }
                    else if (upParticle.myType == 0 && random.rnd.Next(75) == 0)
                    {
                        newParticle.setParticle(ref p, 5);
                    }
                    break;
                #endregion
                #region 5: fire
                case 5:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    ammount = (byte)random.rnd.Next(3);
                    if (ammount > 0)
                    {
                        //if (upParticle == null)
                        {
                            world.swap(x, y, x, y + 1);
                        }
                        RightParticle = x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank;
                        LeftParticle = world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank;
                        world.swap(x, y, (uint)(x + (RightParticle.myType == 0 && !(LeftParticle.myType == 0) || random.rnd.Next(2) == 0 ? -ammount : ammount)), y);
                    }
                    if (random.rnd.Next(25) == 0 || upParticle.myType == 3)
                        newParticle.setParticle(ref p, 0);
                    break;
                #endregion
                #region 6: obsidian
                case 6:
                    break;
                #endregion
                #region 7: ash
                case 7:
                    upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
                    downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
                    ammount = (byte)random.rnd.Next(2);
                    RightParticle = ammount > 0 ? (x >= ammount ? world.worldParticleLayer[(x - ammount) * world.arraywidth + y] : blank) : blank;
                    LeftParticle = ammount > 0 ? (world.arraywidth > y + ammount ? world.worldParticleLayer[(x + ammount) * world.arraywidth + y] : blank) : blank;
                    if (downParticle.myType == 0 || downParticle.myType == 3)
                    {
                        world.swap(x, y, x, y - 1);
                    }
                    else if (downParticle.myType == 7 && ammount > 0)
                    {
                        world.swap(x, y, (uint)(x + ((random.rnd.Next(0, 100) < 50) && !(LeftParticle.myType == 7) ? ammount : !(RightParticle.myType == 7) ? -ammount : 0)), y);
                    }

                    if (downParticle.myType == 6)
                        newParticle.setParticle(ref downParticle, 7);
                    if (upParticle.myType == 6)
                        newParticle.setParticle(ref upParticle, 7);
                    if (LeftParticle.myType == 6)
                        newParticle.setParticle(ref LeftParticle, 7);
                    if (RightParticle.myType == 6)
                        newParticle.setParticle(ref RightParticle, 7);
                    break;
                #endregion
            }
        }
        public static void lightMe(uint x, uint y)
        {
            ThisParticle = world.worldParticleLayer[x * world.arraywidth + y];
            upParticle = world.arrayheight > y + 1 ? world.worldParticleLayer[x * world.arraywidth + y + 1] : blank;
            downParticle = y >= 1 ? world.worldParticleLayer[x * world.arraywidth + y - 1] : blank;
            RightParticle = x >= 1 ? world.worldParticleLayer[(x - 1) * world.arraywidth + y] : blank;
            LeftParticle = world.arraywidth > x + 1 ? world.worldParticleLayer[(x + 1) * world.arraywidth + y] : blank;
            ThisParticle.L = upParticle.L > ThisParticle.L ? upParticle.L : ThisParticle.L;
            ThisParticle.L = RightParticle.L > ThisParticle.L ? RightParticle.L : ThisParticle.L;
            ThisParticle.L = LeftParticle.L > ThisParticle.L ? LeftParticle.L : ThisParticle.L;
            ThisParticle.L = downParticle.L > ThisParticle.L ? downParticle.L : ThisParticle.L;
            switch (ThisParticle.myType)
            {
                case 5:
                    ThisParticle.L += (byte)(ThisParticle.L <= 230 ? 2 : 0);
                    break;
                case 4:
                    ThisParticle.L += (byte)(ThisParticle.L <= 240 ? 1 : 0);
                    break;
                case 0: //empty
                    ThisParticle.L -= (byte)(ThisParticle.L >= 1 ? 1 : 0);
                    break;
                case 3: //water
                case 7: //ash
                    ThisParticle.L -= (byte)(ThisParticle.L >= 2 ? 2 : 0);
                    break;
                case 1: //sand
                case 2: //stone
                    ThisParticle.L -= (byte)(ThisParticle.L >= 4 ? 4 : 0);
                    break;
            }
            world.worldParticleLayer[x * world.arraywidth + y] = ThisParticle;
        }
    }
}
